﻿using System;
using System.Collections.Generic;
using Spring.Data.NHibernate.Generic.Support;
using Spring.Data.NHibernate.Generic;
using NHibernate;

namespace BigMouse.Framework
{
    public class NHibernateDao<T> : HibernateDaoSupport, IDao<T>
    {
        public int save(T entity)
        {
            int id = (int)this.HibernateTemplate.Save(entity);
            return id;
        }

        public void update(T entity)
        {
            this.HibernateTemplate.Update(entity);
        }

        public void delete(T entity)
        {
            this.HibernateTemplate.Delete(entity);
        }

        public void delete(int id)
        {
            this.delete(this.get(id));
        }

        public T get(int id)
        {
            return this.HibernateTemplate.Get<T>(id);
        }

        public IList<T> query(string hql, object[] values)
        {
            IList<T> list = this.HibernateTemplate.ExecuteFind<T>(new HqlQueryCallback<T>(this.HibernateTemplate, hql, values, 0, 0));
            return list;
        }

        public IList<T> query(string hql, object[] values, int pageSize, int currentPage)
        {
            IList<T> list = this.HibernateTemplate.ExecuteFind<T>(new HqlQueryCallback<T>(this.HibernateTemplate, hql, values, pageSize, currentPage));
            return list;
        }
    }

    internal class HqlQueryCallback<L> : IFindHibernateCallback<L>
    {
        private HibernateTemplate _template;
        private string _hql;
        private object[] _values;
        private int _pageSize;
        private int _currentPage;

        public HqlQueryCallback(HibernateTemplate template, string hql, object[] values, int pageSize, int currentPage)
        {
            this._template = template;
            this._hql = hql;
            this._values = values;
            this._pageSize = pageSize;
            this._currentPage = currentPage;
        }

        public IList<L> DoInHibernate(ISession session)
        {
            IQuery queryObject = session.CreateQuery(_hql);
            _template.PrepareQuery(queryObject);

            if (_values != null)
            {
                for (int i = 0; i < _values.Length; i++)
                {
                    queryObject.SetParameter(i, _values[i]);
                }
            }

            if (_pageSize > 0)
            {
                int startIndex = _pageSize * (_currentPage - 1);
                queryObject.SetFirstResult(startIndex);
                queryObject.SetMaxResults(startIndex + _pageSize);
            }

            return queryObject.List<L>();
        }
    }
}
